package org.noootsab.gae.games.tzaar.model.game {
import com.adobe.serialization.json.JSON;

import mx.logging.ILogger;
import mx.logging.Log;

import org.noootsab.gae.games.tzaar.event.PieceEvent;

[Bindable]
public class Piece {
    private static var LOG:ILogger = Log.getLogger("org.noootsab.gae.games.tzaar.model.game.Piece");

    // 6 tzaars, 9 tzarras, and 15 totts
    public static const TZAAR:uint = 0;
    public static const TZARRA:uint = 1;
    public static const TOTT:uint = 2;

    public var game:Game;

    public var line:uint;
    public var cell:uint;
    public var type:uint;
    public var black:Boolean;

    public var stack:Array = [];
    public var stackedBy:Piece = null;
    public var takenBy:Piece = null;
    public var took:Array = [];

    public function Piece() {

    }

    public function init(game:Game, line:uint, cell:uint, type:uint, black:Boolean):void {
        this.game = game;
        this.line = line;
        this.cell = cell;
        this.type = type;
        this.black = black;
    }

    public function stackOn(stacked:Piece):void {
        var action:GameAction = new GameAction(GameAction.STACK_ON, this, [line, cell], stacked, [stacked.line, stacked.cell]);

        stacked.stackedBy = this;
        stacked.stack = null;

        if (stack == null) {
            stack = [];
        }

        stack.push(stacked);
        moveOn(stacked);
        dispatchEvent(new PieceEvent(PieceEvent.STACK_ON_EVENT, stacked));
        stacked.dispatchEvent(new PieceEvent(PieceEvent.STACKED_BY_EVENT, this));

        game.play(action);
    }

    public function take(taken:Piece):void {
        var action:GameAction = new GameAction(GameAction.TAKE, this, [line, cell], taken, [taken.line, taken.cell]);

        taken.takenBy = this;
        took.push(taken);
        moveOn(taken);
        dispatchEvent(new PieceEvent(PieceEvent.TAKE_EVENT, taken));
        taken.dispatchEvent(new PieceEvent(PieceEvent.TAKEN_BY_EVENT, this));

        game.play(action);
    }

    private function moveOn(on:Piece):void {
        game.boardConfiguration.matrix[on.line][on.cell] = this;
        game.boardConfiguration.matrix[line][cell] = null;
        line = on.line;
        cell = on.cell;
    }

    public function get strength():uint {
        if (stack === null) {
            return 0;
        } else {
            return stack.length + 1;
        }
    }

    public static function fromJSON(line:uint, cell:uint, game:Game, json:*):Piece {
        var p:Piece = new Piece();
        var jsonObject:Object;
        if (json is String) {
            jsonObject = JSON.decode(json) as Object;
        } else if (json is Object) {
            jsonObject = json;
        } else {
            throw new Error("Bad Json given");
        }
        p.init(game, line, cell, jsonObject.type, jsonObject.black);

        p.stack = null;
        if (jsonObject.stack && jsonObject.stack is Array && jsonObject.stack.length > 0) {
            p.stack = [];
            var jsonStack:Array = jsonObject.stack as Array;
            for (var i:uint = 0 ; i < jsonStack.length ; i++) {
                var piece:Piece = Piece.fromJSON(line, cell, game, jsonStack[i]);
                p.stack.push(piece)
            }
        }
        return p;
    }

    public static function toJSON(p:Piece):String {
        var json:String = "{";
        json += "\"type\":"+p.type+",";
        json += "\"black\":"+p.black;
        if (p.stack != null) {
            json += ",";
            json += "\"stack\":[";
            var s:Array = p.stack;
            for (var i:uint = 0 ; i < s.length ; i++) {
                json += Piece.toJSON(s[i]);
                if (i != s.length-1) {
                    json += ",";
                }
            }
            json += "]";
        }
        json += "}";        
        return json;
    }
}
}